<template>
  <div class="re-table">
    <el-table :data="props.data" v-bind="tableAttrsDefault" ref="TableRef" :row-key="getRowKeys"
      @selection-change="handleSelectionChange" @sort-change="sortChange">
      <el-table-column v-if="showSelection" type="selection" width="50" align="left" :selectable="selectInit"
        reserve-selection />
      <template v-for="propItem in configs" :key="propItem.prop">
        <el-table-column v-if="!propItem.hidden ?? true" v-bind="propItem"
          :align="propItem.align ? propItem.align : 'left'"
          :show-overflow-tooltip="propItem.showOverflowTooltip !== false">
          <template #default="scope">
            <slot :name="propItem.slotName" :row="scope.row">
              <span v-if="propItem.callback" :class="propItem.class && propItem.class(scope.row)"
                :style="propItem.style && propItem.style(scope.row)">
                {{ propItem.callback && propItem.callback(scope.row) }}
              </span>
              <span v-else-if="propItem.open" class="table-open" @click="propItem.open(scope.row)">
                {{ scope.row[propItem.prop] }}</span>
              <span v-else> {{ scope.row[propItem.prop] }}</span>
            </slot>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <el-pagination v-if="isShowPag" class="mt-5" :total="total" v-bind="paginationAttrsDefault"
      @size-change="handleSizeChange" @current-change="handleCurrentChange" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from "vue";
import type { ElTable, TableColumnCtx, TableProps } from "element-plus";
import type { PaginationProps } from "element-plus/es/components/pagination/src/pagination";
import { noop } from "lodash";

type CallbackType = (row: any) => string | number;

interface configType extends TableColumnCtx<any> {
  hidden?: boolean;
  callback?: CallbackType;
  open?: Function;
  slotName?: string;
  class?: Function;
  style?: Function;
}

interface Props<T = []> {
  configs?: configType[]; // 表格配置
  data?: T[]; // 表格数据
  showSelection?: boolean; // 是否显示选择器
  selectFilter?: Function; // 选择器过滤
  isShowPag?: boolean; // 是否显示分页器
  total?: number; // 分页器总数
  hooks?: Function; // 分页器回调
  paginationAttrs?: PaginationProps; // 分页器配置
  tableAttrs?: TableProps<T>; // table配置
}

const props = withDefaults(defineProps<Props>(), {
  showSelection: false,
  isShowPag: true,
  total: 0,
  hooks: () => noop
});
/**
 * @description: table默认配置, 可扩展, 可合并
 */
const tableAttrsDefault = computed(() => {
  return Object.assign(
    {
      border: true,
      stripe: true,
      maxHeight: "100%"
    },
    props.tableAttrs
  );
});
/**
 * @description: 分页器默认配置, 可扩展, 可合并
 */
const paginationAttrsDefault = computed(() => {
  return Object.assign(
    {
      disabled: false,
      pageSizes: [10, 20, 30, 40],
      small: true,
      background: true,
      layout: "total, sizes, prev, pager, next "
    },
    props.paginationAttrs
  );
});
const getRowKeys = row => {
  return row.id;
};

const emits = defineEmits(["selectionChange", "sortChange"]);
const handleSelectionChange = (data: any) => {
  emits("selectionChange", data);
};
const sortChange = (data: any) => {
  emits("sortChange", data);
};
const selectInit = (row: any, index: number) => {
  if (props.selectFilter) {
    return props.selectFilter(row, index);
  } else {
    return true;
  }
};

const handleSizeChange = value => {
  props.hooks({ limit: value });
};
const handleCurrentChange = value => {
  props.hooks({ page: value });
};

const TableRef = ref<InstanceType<typeof ElTable>>();
/**
 * @description: 暴露 清空用户选择方法
 */
const clearSection = () => {
  TableRef.value.clearSelection();
};

const clearSort = () => {
  TableRef.value.clearSort();
};

defineExpose({
  TableRef,
  clearSection,
  clearSort
});
</script>

<style scoped lang="scss">
.table-open {
  color: #15559a;
  cursor: pointer;
}
</style>
